package com.huiyeji.mail.trigger;

import com.huiyeji.mail.trigger.processor.EmailProcessor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.search.FlagTerm;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmailMonitor implements InitializingBean {

    private static final String appName = "Hsp Mail Trigger";

    private static final SimpleDateFormat  dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final Logger logger = LogManager.getLogger(EmailMonitor.class);

    private static final Set<Long> processUids = new HashSet<>();

    private static final Object lock = new Object();

    private Properties properties;
    private Session session;
    private Store store;
    private Folder inbox;

    private final String host;

    private final String port;

    private final String username;

    private final String password;

    private final String protocol;


    private final int intervalMinutes;

    private final EmailProcessor processor;

    private final CacheCleaner cacheCleaner;

    public EmailMonitor(HspMailTriggerProperties hspMailTriggerProperties,EmailProcessor emailProcessor) {
        this.host = hspMailTriggerProperties.getHost();
        this.port = hspMailTriggerProperties.getProtocol().getPort();
        this.username = hspMailTriggerProperties.getUsername();
        this.password = hspMailTriggerProperties.getPassword();
        this.protocol = hspMailTriggerProperties.getProtocol().getProtocol();
        this.intervalMinutes = hspMailTriggerProperties.getIntervalMinutes();
        this.processor = emailProcessor;
        this.cacheCleaner = new CacheCleaner(()->{
            synchronized (getLock()) {
                getProcessUids().clear();
                logger.info("缓存已清理");
            }
        });
    }

    private void initializeProperties() {
        properties = new Properties();
        properties.put("mail.store.protocol", protocol);
        properties.put("mail." + protocol + ".host", host);
        properties.put("mail." + protocol + ".port", port);

//        if ("imaps".equals(protocol)) {
//            properties.put("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//            properties.put("mail.imap.socketFactory.fallback", "false");
//            properties.put("mail.imap.socketFactory.port", port);
//        }

        // 根据需要添加更多属性
        properties.put("mail.debug", "false");


        // 基础配置
        properties.put("mail.store.protocol", protocol);
//        properties.put("mail.imaps.host", host);
//        properties.put("mail.imaps.port", port);
//        properties.put("mail.imaps.ssl.enable", "true");
//        properties.put("mail.imaps.starttls.enable", "true");
//        properties.put("mail.imaps.auth", "true");
//
//        // 解决常见连接问题
//        properties.put("mail.imaps.connectiontimeout", "10000");
//        properties.put("mail.imaps.timeout", "10000");
//        properties.put("mail.imaps.writetimeout", "10000");
//
//        // 认证机制配置
        properties.put("mail.imaps.auth.mechanisms", "XOAUTH2 PLAIN LOGIN");
//        properties.put("mail.imaps.auth.plain.disable", "false");
//        properties.put("mail.imaps.auth.login.disable", "false");
    }

    public void connect() throws MessagingException {
        session = Session.getInstance(properties);
        store = session.getStore(protocol);
        store.connect(host, username, password);
        inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_WRITE);

        logger.info("成功连接到邮箱: {}", username);
    }

    public void disconnect() {
        try {
            if (inbox != null && inbox.isOpen()) {
                inbox.close(false);
            }
            if (store != null && store.isConnected()) {
                store.close();
            }
            logger.info("已断开邮箱连接");
        } catch (MessagingException e) {
            logger.error("断开连接时出错: {}", e.getMessage());
        }
    }

    public void startMonitoring(int intervalMinutes) {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

        scheduler.scheduleAtFixedRate(() -> {
            try {
                if (!inbox.isOpen()){
                    inbox.open(Folder.READ_WRITE);
                }
                synchronized (lock){
                    checkForNewEmails();
                }
                inbox.close(false);
            } catch (Exception e) {
                logger.error("检查邮件时出错: {}", e.getMessage());
                // 可以选择重新连接
                try {
                    disconnect();
                    connect();
                } catch (MessagingException ex) {
                    logger.error("重新连接失败: {}", ex.getMessage());
                }
            }
        }, 0, intervalMinutes, TimeUnit.MINUTES);

        logger.info("开始监控邮箱，每 {} 分钟检查一次新邮件", intervalMinutes);
    }

    private void checkForNewEmails() throws MessagingException, InterruptedException {
        // 检查新邮件
        List<Message> unreadEmails = getUnreadEmails();

        if (!unreadEmails.isEmpty()) {
            logger.info("监听到 {} 封新邮件", unreadEmails.size());

            UIDFolder uidFolder = (UIDFolder) inbox;

            for (Message message : unreadEmails) {
                long uid = uidFolder.getUID(message);

                try {
                    processMessage(message,String.valueOf(uid));
                    processUids.add(uid);
                    // 标记为已读
                    message.setFlag(Flags.Flag.SEEN, true);

                } catch (Exception e) {
                    logger.error("处理邮件时出错: {}", e.getMessage());
                    e.printStackTrace();
                }

            }
        }

    }

    private void processMessage(Message message,String uid) throws Exception {
        // 解析邮件内容
        String from = getSafeSender(message);
        String subject = message.getSubject();
        Date sentDate = message.getSentDate();
        String content = getTextFromMessage(message);

        logger.info("处理邮件 - 发件人: {}, 主题: {}", from, subject);

        // 调用处理器处理邮件
        if (processor != null) {
            EmailBody emailBody = new EmailBody();
            emailBody.setUid(uid);
            emailBody.setSubject(subject);
            emailBody.setContent(content);
            emailBody.setFrom(from);
            emailBody.setSentDate(dateFormat.format(sentDate));
            emailBody.setOriginalMessage(message);

            processor.processEmail(emailBody);
        } else {
            logger.error("未找到EmailProcessor,不进行处理");
        }
    }

    private String getTextFromMessage(Message message) throws Exception {
        if (message.isMimeType("text/plain")) {
            return message.getContent().toString();
        } else if (message.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) message.getContent();
            return getTextFromMimeMultipart(multipart);
        }
        return "";
    }

    private String getTextFromMimeMultipart(Multipart multipart) throws Exception {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            if (bodyPart.isMimeType("text/plain")) {
                result.append(bodyPart.getContent());
                break; // 优先使用纯文本部分
            } else if (bodyPart.isMimeType("text/html")) {
                String html = (String) bodyPart.getContent();
                // 可以添加HTML到纯文本的转换逻辑
                result.append(html);
            } else if (bodyPart.getContent() instanceof Multipart) {
                result.append(getTextFromMimeMultipart((Multipart) bodyPart.getContent()));
            }
        }
        return result.toString();
    }

    public Set<Long> getProcessUids() {
        return processUids;
    }

    public Object getLock() {
        return lock;
    }

    public void start(){
        try {
            // 连接邮箱
            connect();

            // 开始监控
            startMonitoring(intervalMinutes);

//

        } catch (Exception e) {
            logger.error("发生错误: {}", e.getMessage());
            e.printStackTrace();
        }
    }


    // 获取未读邮件
    public List<Message> getUnreadEmails() throws MessagingException {
        List<Message> unreadMessages = new ArrayList<>();

        if (!store.isConnected()) {
            throw new IllegalStateException("未连接到邮箱");
        }

        try {
            UIDFolder uidFolder = (UIDFolder) inbox;

            // 获取所有未读邮件
            Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));

            for (Message message : messages) {
                if (!processUids.contains(uidFolder.getUID(message))) {
                    unreadMessages.add(message);
                }
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return unreadMessages;
    }

    private String getSafeSender(Message message) {
        try {
            // 首先尝试Reply-To
            Address[] replyTos = message.getReplyTo();
            if (replyTos != null && replyTos.length > 0) {
                return ((InternetAddress) replyTos[0]).getAddress();
            }

            // 然后尝试From
            Address[] froms = message.getFrom();
            if (froms != null && froms.length > 0) {
                return ((InternetAddress) froms[0]).getAddress();
            }

            // 最后尝试原始头部
            String[] fromHeaders = message.getHeader("From");
            if (fromHeaders != null && fromHeaders.length > 0) {
                // 简单提取邮箱地址
                String header = fromHeaders[0];
                int start = header.indexOf('<');
                int end = header.indexOf('>');
                if (start != -1 && end != -1 && start < end) {
                    return header.substring(start + 1, end).trim();
                }

                // 尝试匹配邮箱格式
                Pattern pattern = Pattern.compile("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b", Pattern.CASE_INSENSITIVE);
                Matcher matcher = pattern.matcher(header);
                if (matcher.find()) {
                    return matcher.group();
                }
            }

        } catch (Exception e) {
            // 记录错误
        }

        return "unknown@example.com";
    }


    private void printSimpleLogo() {

        String logo = "╔══════════════════════════════════════════════════╗\n" +
                "║    ██╗  ██╗███████╗██████╗     ███╗   ███╗       ║\n" +
                "║    ██║  ██║██╔════╝██╔══██╗    ████╗ ████║       ║\n" +
                "║    ███████║███████╗██████╔╝    ██╔████╔██║       ║\n" +
                "║    ██╔══██║╚════██║██╔═══╝     ██║╚██╔╝██║       ║\n" +
                "║    ██║  ██║███████║██║         ██║ ╚═╝ ██║       ║\n" +
                "║    ╚═╝  ╚═╝╚══════╝╚═╝         ╚═╝     ╚═╝       ║\n" +
                "║                                                  ║\n" +
                "║         H S P   M A I L   T R I G G E R          ║\n" +
                "║                                                  ║\n" +
                "╚══════════════════════════════════════════════════╝";

        System.out.println(logo);
    }



    @Override
    public void afterPropertiesSet() throws Exception {
        printSimpleLogo();
        initializeProperties();
        start();
    }
}